qemu 16550 uart: Fast-drop bursts of transmitted characters to avoid
authorKeir Fraser <keir.fraser@citrix.com>
Sat, 8 Dec 2007 15:46:04 +0000 (15:46 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Sat, 8 Dec 2007 15:46:04 +0000 (15:46 +0000)
stalling due to a disconnected pipe or pty.
Signed-off-by: Trolle Selander <trolle.selander@gmail.com>
tools/ioemu/hw/serial.c

index 952f5b955c1771410e9bfae0e7bc6303fa7737d8..af6aa64ee350c224940094c967ca3da00e029762 100644 (file)
@@ -359,7 +359,7 @@ static void serial_xmit(void *opaque) {
     SerialState *s = opaque;
     uint64_t new_xmit_ts = qemu_get_clock(vm_clock);
     
-    if ( s->tsr_retry == 0 ) {
+    if ( s->tsr_retry <= 0 ) {
         if (s->fcr & UART_FCR_FE) {
             s->tsr = fifo_get(s,XMIT_FIFO);
             if ( !s->xmit_fifo.count )
@@ -371,16 +371,22 @@ static void serial_xmit(void *opaque) {
     }
 
     if ( qemu_chr_write(s->chr, &s->tsr, 1) != 1 ) {
-        s->tsr_retry++;
-        if ( s->tsr_retry <= MAX_XMIT_RETRY ) {
+        if ( ( s->tsr_retry > 0 ) && ( s->tsr_retry <= MAX_XMIT_RETRY ) ) {
+            s->tsr_retry++;
             qemu_mod_timer(s->transmit_timer,  new_xmit_ts + s->char_transmit_time );
             return;
+        } else if ( s->poll_msl < 0 ) {
+            /* If we exceed MAX_XMIT_RETRY and the backend is not a real serial port, then
+            drop any further failed writes instantly, until we get one that goes through.
+            This is to prevent guests that log to unconnected pipes or pty's from stalling. */
+            s->tsr_retry = -1;
         }
     }
-    s->tsr_retry = 0;
-    s->last_xmit_ts = qemu_get_clock(vm_clock);
+    else {
+        s->tsr_retry = 0;
+    }
 
+    s->last_xmit_ts = qemu_get_clock(vm_clock);
     if ( !(s->lsr & UART_LSR_THRE) )
         qemu_mod_timer(s->transmit_timer, s->last_xmit_ts + s->char_transmit_time );